using System;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace ClientJIP
{
	public class NetworkChat
	{
		// Socket
		private TcpClient Client;
		// Streams
		private NetworkStream ClientStream;
		private StreamReader ClientReader;
		private StreamWriter ClientWriter;
		// Chat data
		private Chat ChatClient;
		// Threads
		private Thread thCheckReceivedData;
		// Indicators
		public bool Running {get; private set;}
		
		private Mutex mutexStream = new Mutex();
		
		
		/// <summary>
		/// Create a new network chat
		/// </summary>
		/// <param name="chatClient">
		/// A <see cref="Chat"/>
		/// </param>
		public NetworkChat (Chat chatClient)
		{
			ChatClient = chatClient;
			Client = new TcpClient();
		}
		
		/// <summary>
		/// Connect to network server
		/// </summary>
		/// <param name="host">
		/// A <see cref="String"/>
		/// </param>
		/// <param name="port">
		/// A <see cref="Int32"/>
		/// </param>
		/// <returns>
		/// A <see cref="System.Boolean"/>
		/// </returns>
		public bool Start(String host, Int32 port)
		{
			try {
				// Start connexion
				Client.Connect(host,port);
				
				// Allocate streams
				ClientStream = Client.GetStream();
				ClientReader = new StreamReader(ClientStream);
				ClientWriter = new StreamWriter(ClientStream);
				ClientWriter.AutoFlush = true;
				
				// Launch thread : check if data received
				thCheckReceivedData = new Thread(CheckReceivedData);
            	thCheckReceivedData.Start();
				
				// Indicator
				Running = true;
				
				return true;
			} catch {
				return false;
			}
		}
		
		/// <summary>
		/// Disconnect from network server
		/// </summary>
		/// <returns>
		/// A <see cref="System.Boolean"/>
		/// </returns>
		public bool Stop()
		{
			try {
				// Close thread
				thCheckReceivedData.Abort();
				thCheckReceivedData.Join();
				
				// Close streams
				ClientReader.Close();
				ClientWriter.Close();
				ClientStream.Close();
				
				// Indicator
				Running = false;
				
				// Close connexion
				Client.Close();
				Client = new TcpClient();
				
				return true;
			} catch {
				return false;	
			}
		}
		
		/// <summary>
		/// Write a line to the socket buffer
		/// </summary>
		/// <param name="message">
		/// A <see cref="String"/>
		/// </param>
		public void WriteLine(String message)
		{
			mutexStream.WaitOne();
			
           if(message != String.Empty && Client.Connected)
				ClientWriter.WriteLine(message);
			
			mutexStream.ReleaseMutex();
			
		}
		
		/// <summary>
		/// Read a line from the socket buffer
		/// </summary>
		/// <returns>
		/// A <see cref="String"/>
		/// </returns>
		public String ReadLine()
		{
			mutexStream.WaitOne();
			
			string line;
			if(Client.Connected && IsDataAvailable())
				line = ClientReader.ReadLine();
			else
				line = String.Empty;
			
			mutexStream.ReleaseMutex();
			
			return line;
		}
		
		/// <summary>
		/// Return if data are available in the socket buffer
		/// </summary>
		/// <returns>
		/// A <see cref="System.Boolean"/>
		/// </returns>
		public bool IsDataAvailable()
		{
			if(Client.Connected)
				return ClientStream.DataAvailable;
			else
				return false;
		}
		
		/// <summary>
		/// Threaded method : check if data received
		/// </summary>
		private void CheckReceivedData()
		{
			while(thCheckReceivedData.IsAlive) {
				if(IsDataAvailable())
					ChatClient.ReadLine();
				else {
					Thread.Sleep(10);
				}
			}
		}
	}
}

